﻿//(c) Copyright [2015] Hewlett-Packard Enterprise Development, L.P.
//All rights reserved.
//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
//1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
//THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 
//BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
//OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace HP.HPTRIM.Samples.Thumbnails
{
    /// <summary>
    /// This does the conversion to thumbnail.  All  of the code is 'borrowed' directly from Dan Byström ( http://danbystrom.se/2009/01/05/imagegetthumbnailimage-and-beyond/)
    /// </summary>
    public class ThumbnailGenerator
    {
        private string _filePath;
        private string _originalFileName;
        public ThumbnailGenerator(string fromFile, string originalFileName)
        {
            _filePath = fromFile;
            _originalFileName = originalFileName;
        }


        private Bitmap getExifThumbnail(string filename)
        {
            using (FileStream fs = File.OpenRead(filename))
            using (Image img = Image.FromStream(fs, true, false))
            {
                foreach (PropertyItem pi in img.PropertyItems)
                    if (pi.Id == 20507)
                        return (Bitmap)Image.FromStream(new MemoryStream(pi.Value));
            }
            return null;
        }

        private Bitmap getThumbnailImage()
        {
            // check if there is a thumbnail embedded in the image first, if so us that.
            Bitmap exIf = getExifThumbnail(_filePath);

            if (exIf != null)
            {
                return exIf;
            }

            using (FileStream fs = File.OpenRead(_filePath))
            using (Image img = Image.FromStream(fs, true, false))
            {

                Size sz = adaptProportionalSize(new Size(250, 250), img.Size);
                return ((Bitmap)img.GetThumbnailImage(
                   sz.Width,
                   sz.Height,
                   null,
                   IntPtr.Zero));
            }
        }
        public TempFile MakeThumbnail()
        {
            string thumbnailName = Path.Combine(Path.GetTempPath(), string.Format("thumbnail_{0}", _originalFileName));

            getThumbnailImage().Save(thumbnailName);

            if (File.Exists(thumbnailName))
            {
                return new TempFile(thumbnailName);
            }

            return new TempFile();
        }

        public byte[] GetThumbnail()
        {
            Image thumbnail = getThumbnailImage();
            ImageConverter converter = new ImageConverter();
            return (byte[])converter.ConvertTo(thumbnail, typeof(byte[]));
        }

        private static Size adaptProportionalSize(Size szMax, Size szReal)
        {
            int nWidth;
            int nHeight;
            double sMaxRatio;
            double sRealRatio;
            if (szMax.Width < 1 || szMax.Height < 1 || szReal.Width < 1 || szReal.Height < 1)
                return Size.Empty;
            sMaxRatio = (double)szMax.Width / (double)szMax.Height;
            sRealRatio = (double)szReal.Width / (double)szReal.Height;
            if (sMaxRatio < sRealRatio)
            {
                nWidth = Math.Min(szMax.Width, szReal.Width);
                nHeight = (int)Math.Round(nWidth / sRealRatio);
            }
            else
            {
                nHeight = Math.Min(szMax.Height, szReal.Height);
                nWidth = (int)Math.Round(nHeight * sRealRatio);
            }
            return new Size(nWidth, nHeight);
        }
    }
}